home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 January: Mac OS SDK / Dev.CD Jan 98 SDK2.toast / Development Kits (Disc 2) / QuickDraw GX / Programming Stuff / Sample Code / Printing Samples / Applications… / QuickDraw GX Aware Sample ƒ / Simple Sample ƒ / file.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-20  |  11.8 KB  |  475 lines  |  [TEXT/MMCC]

  1. /*********************************************************************
  2.  
  3.     files.c
  4.     
  5.     This file contains the file I/O code for the QuickDraw GX unaware
  6.     sample, "Simple Sample."
  7.     
  8.     Additional info can be found in the related develop #19 article,
  9.     "Adding QuickDraw GX Printing to QuickDraw Applications."
  10.  
  11.     Dave Hersey, Apple Developer Technical Support.
  12.     
  13.     ——————— Edit Trail ———————
  14.     
  15.     hatched:                                        1/22/94  - dmh
  16.     cleaned up for 2nd draft of develop article:    3/10/94  - dmh
  17.     cleaned up for final:                            4/14/94  - dmh
  18.     
  19. *********************************************************************/
  20.  
  21. #include "Simple Sample.h"
  22.  
  23.  
  24. /************************************************************
  25.   MyLoadDocument - This routine loads a previously saved
  26.   document.
  27.  
  28. *************************************************************/
  29.  
  30. OSErr MyLoadDocument(MyDocumentPtr whichDocument)
  31. {
  32.     OSErr                err;
  33.     short                oldResFile, dataRefNum = -1, resRefNum = -1;
  34.     StandardFileReply    sfReply;
  35.     SFTypeList            myTypeList;
  36.     WindowPtr            curWindow;
  37.     MyDocumentPtr        windDoc;
  38.     Boolean                notAlreadyOpen;
  39.  
  40. // Let the user select a document to open.
  41.  
  42.     myTypeList[0] = kMyDocType;
  43.     StandardGetFile(nil, 1, myTypeList, &sfReply);
  44.     require_action(sfReply.sfGood, UserHasCancelled, err = iPrAbort;);
  45.  
  46. /*
  47.     Make sure that we haven't already opened this document. If
  48.     we have, just bring the old window forward.
  49. */
  50.     nrequire_action(MyIsWindowAlreadyOpen(&sfReply.sfFile),
  51.                     DocIsAlreadyOpen, err = iPrAbort;);
  52.  
  53. // Open the selected file's data fork and resource fork.
  54.  
  55.     err = FSpOpenDF(&sfReply.sfFile, fsRdWrPerm, &dataRefNum);
  56.     nrequire(err, CouldNotOpenDataFork);
  57.  
  58.     resRefNum = HOpenResFile(sfReply.sfFile.vRefNum, sfReply.sfFile.parID,
  59.                              sfReply.sfFile.name, fsRdPerm);
  60.  
  61.     err = ResError();
  62.     nrequire(err, CouldNotOpenResourceFork);
  63.  
  64. /*
  65.     If we're successful in opening the file, set our document's
  66.     FSSpec info, its title, and its window's title.
  67. */
  68.  
  69.     oldResFile = CurResFile();
  70.     
  71.     BlockMove(&sfReply.sfFile, &whichDocument->documentFSSpec, sizeof(FSSpec));
  72.     BlockMove(&sfReply.sfFile.name, whichDocument->documentTitle,
  73.               (long) sfReply.sfFile.name[0] +1);
  74.     
  75.     SetWTitle(whichDocument->documentWindow, whichDocument->documentTitle);
  76.     err = MyLoadPrintInfo(whichDocument, resRefNum);
  77.  
  78. // Now load the data for our document's pages.
  79.  
  80.     whichDocument->numPages = MyLoadPageCount(resRefNum);
  81.     whichDocument->curPage = 1;
  82.  
  83.     /* 
  84.         Place your application-specific code here to load 
  85.         other data associated with the document.
  86.         .
  87.         .
  88.         .
  89.     */
  90.  
  91.     MyAdjustMenus();
  92.  
  93. // Close the data and resource forks of this document.
  94.  
  95.     UseResFile(oldResFile);
  96.     CloseResFile(resRefNum);
  97.  
  98. CouldNotOpenResourceFork:
  99.     FSClose(dataRefNum);
  100.  
  101. CouldNotOpenDataFork:
  102. DocIsAlreadyOpen:
  103. UserHasCancelled:
  104.     return err;
  105. }
  106.  
  107.  
  108. /************************************************************
  109.   MyFSLoadDocument - This routine opens a document and loads
  110.   its previously saved print record.  It's just like
  111.   MyLoadDocument, but it opens the indicated file and
  112.   doesn't present a file dialog.
  113.  
  114. *************************************************************/
  115.  
  116. OSErr MyFSLoadDocument(MyDocumentPtr whichDocument, FSSpec *docFSSpec, Boolean forPrinting)
  117. {
  118.     OSErr        err;
  119.     short        oldResFile, dataRefNum, resRefNum;
  120.  
  121. /*
  122.     Unless we're printing, make sure that we haven't already opened
  123.     this document. If we have, just bring the old window forward.
  124. */
  125.  
  126.     require_action(forPrinting || !MyIsWindowAlreadyOpen(docFSSpec),
  127.                    DocIsAlreadyOpen, err = iPrAbort;);
  128.  
  129. // Open the selected file's data fork and resource fork.
  130.  
  131.     err = FSpOpenDF(docFSSpec, fsRdWrPerm, &dataRefNum);
  132.     nrequire(err, CouldNotOpenDataFork);
  133.  
  134.     resRefNum = HOpenResFile(docFSSpec->vRefNum, docFSSpec->parID, docFSSpec->name, fsRdPerm);
  135.     err = ResError();
  136.     nrequire(err, CouldNotOpenResourceFork);
  137.  
  138. /*
  139.     If we're successful in opening the file, set our document's
  140.     FSSpec info and its window's title.
  141. */
  142.  
  143.     oldResFile = CurResFile();
  144.  
  145.     BlockMove(docFSSpec, &whichDocument->documentFSSpec, sizeof(FSSpec));
  146.     BlockMove(docFSSpec->name, whichDocument->documentTitle, (long) docFSSpec->name[0] +1);
  147.     SetWTitle(whichDocument->documentWindow, whichDocument->documentTitle);
  148.  
  149.     err = MyLoadPrintInfo(whichDocument, resRefNum);
  150.  
  151. // Now load the data for our document's pages.
  152.  
  153.     whichDocument->numPages = MyLoadPageCount(resRefNum);
  154.     whichDocument->curPage = 1;
  155.  
  156.     /* 
  157.         Place your application-specific code here to load 
  158.         other data associated with the document.
  159.         .
  160.         .
  161.         .
  162.     */
  163.  
  164.     MyAdjustMenus();
  165.  
  166. // Close the data and resource forks of this document.
  167.  
  168.     UseResFile(oldResFile);
  169.     CloseResFile(resRefNum);
  170.  
  171. CouldNotOpenResourceFork:
  172.     FSClose(dataRefNum);
  173.  
  174. CouldNotOpenDataFork:
  175. DocIsAlreadyOpen:
  176.     return err;
  177. }
  178.  
  179.  
  180. /************************************************************
  181.   MyIsWindowAlreadyOpen - This routine compares a file spec
  182.   with those for our currently opened documents.  If we find
  183.   a match, we bring that document's window forward and return
  184.   true.  Otherwise, we return false.
  185.  
  186. *************************************************************/
  187.  
  188. Boolean MyIsWindowAlreadyOpen(FSSpec *whichFSSpec)
  189. {
  190.     WindowPtr        curWindow;
  191.     MyDocumentPtr    curDocument;
  192.     Boolean            isAlreadyOpen = false;
  193.  
  194. /*
  195.     Make sure that we haven't already opened this document. If
  196.     we have, just bring the old window forward and adjust our menus.
  197. */
  198.     curWindow = FrontWindow();
  199.     
  200.     while (curWindow != nil)
  201.     {
  202.         if (((WindowPeek) curWindow)->windowKind == userKind)
  203.         {
  204.             curDocument = MyGetDocPtr(curWindow);
  205.             
  206.             isAlreadyOpen =
  207.                 ((curDocument->documentFSSpec.vRefNum == whichFSSpec->vRefNum) &&
  208.                  (curDocument->documentFSSpec.parID == whichFSSpec->parID) &&
  209.                  (IUEqualString(curDocument->documentFSSpec.name, whichFSSpec->name) == 0));
  210.  
  211.             if (isAlreadyOpen)
  212.             {
  213.                 SelectWindow(curWindow);
  214.                 MyAdjustMenus();
  215.             }
  216.             
  217.             nrequire(isAlreadyOpen, DocIsAlreadyOpen);
  218.         }
  219.     
  220.         curWindow = (WindowPtr) ((WindowPeek) curWindow)->nextWindow;
  221.     }
  222.  
  223. DocIsAlreadyOpen:
  224. NoNeedToCheck:
  225.     return isAlreadyOpen;
  226. }
  227.  
  228.  
  229. /************************************************************
  230.   MySaveDocument - This routine saves a document and its
  231.   corresponding print record to disk.
  232.  
  233. *************************************************************/
  234.  
  235. OSErr MySaveDocument(MyDocumentPtr whichDocument, Boolean doingSaveAs)
  236. {
  237.     OSErr                err = noErr;
  238.     short                dataRefNum, oldResFile, resRefNum;
  239.     FSSpec                *docFSSpec;
  240.     StandardFileReply    sfReply;
  241.     FInfo                docFInfo;
  242.  
  243.     oldResFile = CurResFile();
  244.     docFSSpec = &whichDocument->documentFSSpec;
  245.  
  246. /*
  247.     If we're doing a "Save as…", display the StandardFile
  248.     dialog and have the user select a place to save the file.
  249. */
  250.  
  251.     if (doingSaveAs)
  252.     {
  253.         StandardPutFile("\pSave document:", whichDocument->documentTitle, &sfReply);
  254.         require(sfReply.sfGood, UserHasCancelled);
  255.  
  256. /*
  257.     If we're replacing an existing file, delete it.  Create
  258.     our new file and set its creator and type.
  259. */
  260.         if (sfReply.sfReplacing)
  261.             err = HDelete(sfReply.sfFile.vRefNum, sfReply.sfFile.parID, sfReply.sfFile.name);
  262.  
  263.         nrequire(err, CouldNotDeleteOldFile);
  264.  
  265.         HCreateResFile(sfReply.sfFile.vRefNum, sfReply.sfFile.parID, sfReply.sfFile.name);
  266.         HGetFInfo(sfReply.sfFile.vRefNum, sfReply.sfFile.parID,
  267.                   sfReply.sfFile.name, &docFInfo);
  268.               
  269.         docFInfo.fdCreator = kMyDocCreator;
  270.         docFInfo.fdType = kMyDocType;
  271.  
  272.         err = HSetFInfo(sfReply.sfFile.vRefNum, sfReply.sfFile.parID,
  273.                         sfReply.sfFile.name, &docFInfo);
  274.  
  275. /*
  276.     If we're successful in creating the file, set our document's
  277.     FSSpec info, its title and its window's title.
  278. */
  279.  
  280.         if (err == noErr) err = ResError();
  281.         nrequire(err, CouldNotSetFileInfo);
  282.  
  283.         BlockMove(&sfReply.sfFile, docFSSpec, sizeof(FSSpec));
  284.         BlockMove(&sfReply.sfFile.name, whichDocument->documentTitle,
  285.                   (long) sfReply.sfFile.name[0] +1);
  286.         
  287.         SetWTitle(whichDocument->documentWindow, whichDocument->documentTitle);
  288.     }
  289.  
  290. // Open the file's data fork and resource fork.
  291.  
  292.     err = FSpOpenDF(docFSSpec, fsRdWrPerm, &dataRefNum);
  293.     nrequire(err, CouldNotOpenDataFork);
  294.  
  295.     resRefNum = HOpenResFile(docFSSpec->vRefNum, docFSSpec->parID,
  296.                              docFSSpec->name, fsRdWrPerm);
  297.     err = ResError();
  298.     nrequire(err, CouldNotOpenResourceFork);
  299.  
  300.     err = MySavePrintInfo(whichDocument, resRefNum);
  301.  
  302. // Now save the data for our document's pages.
  303.  
  304.     if (!err)
  305.         err = MySavePageCount(whichDocument, resRefNum);
  306.  
  307.     /* 
  308.         Place your application-specific code here to save 
  309.         other data associated with the document.
  310.         .
  311.         .
  312.         .
  313.     */
  314.  
  315.  
  316. // Close the data and resource forks of this document.
  317.  
  318.     CloseResFile(resRefNum);
  319.  
  320. CouldNotOpenResourceFork:
  321.     FSClose(dataRefNum);
  322.  
  323. CouldNotOpenDataFork:
  324. CouldNotSetFileInfo:
  325. CouldNotDeleteOldFile:
  326. UserHasCancelled:
  327.     UseResFile(oldResFile);
  328.     return err;
  329. }
  330.  
  331.  
  332. /************************************************************
  333.   MySavePageCount - This routine saves a resource containing
  334.   the number of pages in our document.
  335.  
  336. *************************************************************/
  337.  
  338. OSErr MySavePageCount(MyDocumentPtr whichDocument, short resRefNum)
  339. {
  340.     OSErr        err;
  341.     Handle        thePageCount, oldPageCount;
  342.  
  343.     UseResFile(resRefNum);
  344.  
  345. // If there's an existing resource, delete it.
  346.  
  347.     thePageCount = NewHandle(sizeof(long));
  348.     nrequire((err = MemError()), CouldNotCreateHandle);
  349.  
  350.     *(long *)*thePageCount = whichDocument->numPages;
  351.     oldPageCount = Get1Resource(kMyPageCountType, kMyPageCountID);
  352.  
  353.     if (oldPageCount != nil)
  354.     {
  355.         RmveResource(oldPageCount);
  356.         UpdateResFile(resRefNum);
  357.         DisposHandle(oldPageCount);
  358.     }
  359.  
  360. // Add our new resource.
  361.  
  362.     AddResource(thePageCount, kMyPageCountType, kMyPageCountID, "\p");
  363.     err = ResError();
  364.     nrequire(err, CouldNotAddResource);
  365.  
  366.     WriteResource(thePageCount);
  367.     UpdateResFile(resRefNum);
  368.     ReleaseResource(thePageCount);
  369.  
  370. CouldNotAddResource:
  371. CouldNotCreateHandle:
  372.     return err;
  373. }
  374.  
  375.  
  376. /************************************************************
  377.   MyLoadPageCount - This routine loads a resource containing
  378.   the number of pages in our document, and returns the number
  379.   of pages.
  380.  
  381. *************************************************************/
  382.  
  383. long MyLoadPageCount(short resRefNum)
  384. {
  385.     Handle        thePageCount;
  386.     long        numPages;
  387.  
  388.     UseResFile(resRefNum);
  389.  
  390. // Get the page count.  If we don't find a count, return 1.
  391.  
  392.     thePageCount = Get1Resource(kMyPageCountType, kMyPageCountID);
  393.  
  394.     if (thePageCount != nil)
  395.     {
  396.         numPages = *(long *)*thePageCount;
  397.         ReleaseResource(thePageCount);
  398.     }
  399.     else
  400.         numPages = 1;
  401.  
  402.     return numPages;
  403. }
  404.  
  405.  
  406. /************************************************************
  407.   MySavePrintInfo - This routine saves our print record with
  408.   the document, so that it can be used the next time the
  409.   document is opened.
  410.  
  411. *************************************************************/
  412.  
  413. OSErr MySavePrintInfo(MyDocumentPtr whichDocument, short resRefNum)
  414. {
  415.     OSErr        err;
  416.     Handle        thePrintData, oldPrintData;
  417.  
  418.     UseResFile(resRefNum);
  419.  
  420. // If there's an existing resource, delete it.
  421.  
  422.     thePrintData = (Handle) whichDocument->documentPrintHdl;
  423.     oldPrintData = Get1Resource(kMyPrintRecType, kMyPrintRecID);
  424.  
  425.     if (oldPrintData != nil)
  426.     {
  427.         RmveResource(oldPrintData);
  428.         UpdateResFile(resRefNum);
  429.         DisposHandle(oldPrintData);
  430.     }
  431.  
  432. // Add our new resource.
  433.  
  434.     AddResource(thePrintData, kMyPrintRecType, kMyPrintRecID, "\p");
  435.     err = ResError();
  436.     nrequire(err, CouldNotAddResource);
  437.  
  438.     WriteResource(thePrintData);
  439.     UpdateResFile(resRefNum);
  440.     DetachResource(thePrintData);
  441.  
  442. CouldNotAddResource:
  443.     return err;
  444. }
  445.  
  446.  
  447. /************************************************************
  448.   MyLoadPrintInfo - This routine loads our document's
  449.   previously saved print record.
  450.  
  451. *************************************************************/
  452.  
  453. OSErr MyLoadPrintInfo(MyDocumentPtr whichDocument, short resRefNum)
  454. {
  455.     THPrint        savedPrintHdl;
  456.  
  457.     UseResFile(resRefNum);    
  458.  
  459. /*
  460.     Try to load a previously saved print record.  If we find one,
  461.     dispose of the print handle that we allocated in our
  462.     MyCreateDocument routine.
  463. */
  464.     savedPrintHdl = (THPrint) Get1Resource(kMyPrintRecType, kMyPrintRecID);
  465.  
  466.     if (savedPrintHdl != nil)
  467.     {
  468.         DetachResource((Handle) savedPrintHdl);
  469.         DisposHandle((Handle) whichDocument->documentPrintHdl);
  470.         whichDocument->documentPrintHdl = savedPrintHdl;
  471.     }
  472.     
  473.     return noErr;
  474. }
  475.